#pragma once

#include "doc/normal_document.h"
#include "index/index.h"
#include "index/attribute_index/attribute_filter/attribute_filter.h"

namespace hawking {
namespace indexlib {

class AttributeIndexer {
public:
    AttributeIndexer(
        int32_t field_id,
        util::ColumnType field_type,
        std::shared_ptr<AttributeConvertor> attribute_convertor) :
            field_id_(field_id),
            field_type_(field_type),
            attribute_convertor(attribute_convertor) {}
    virtual ~AttributeIndexer() = default;

    virtual uint64_t DocCount() const = 0;

    virtual uint32_t ElementLength() const = 0;

    static void Filter(
        SegmentContext* segment_ctx,
        const util::FilterColumn& filter_field,
        util::ColumnType field_type,
        int32_t field_id,
        bool is_where = false);

    virtual Status BatchRead(SegmentContext* segment_ctx) = 0;

    util::ColumnType GetColumnType() const {
        return field_type_;
    }

    int32_t FieldId() const {
        return field_id_;
    }

    util::HawkingRecallRetCode UpdateDocument(DocId doc_id, NormalDocument* doc) {
        const std::string_view& field_data = GetFieldData_(doc);
        if (field_data.empty()) {
            return Status::OK;
        }

        return UpdateField_(doc_id, field_data);
    }

    std::shared_ptr<AttributeConvertor> AttrConvertor() {
        return attribute_convertor_;
    }

protected:
    const std::string_view& GetFieldData_(NormalDocument* doc) const {
        std::shared_ptr<AttributeDocument> attr_doc = doc->GetAttributeDocument();
        return attr_doc->GetField(field_id_);
    }

    virtual util::HawkingRecallRetCode UpdateField_(
        DocId doc_id, const std::string_view& value) = 0;
    
    int32_t field_id_ = -1;
    util::ColumnType field_type_ = util::COLUMN_UNKNOW;
    std::shared_ptr<AttributeConvertor> attribute_convertor_;
};

}
}